﻿-- this file must be encoded by UTF-8 and be run by LuaJIT 2
-- 导入 RealLive反编译tobc脚本 中字符串的程序 (by dwing)

local ffi = require("ffi")
ffi.cdef[[
int __stdcall MultiByteToWideChar(int cp, int flag, const char* src, int srclen, char* dst, int dstlen);
int __stdcall WideCharToMultiByte(int cp, int flag, const char* src, int srclen, char* dst, int dstlen, const char* defchar, int* used);
]]
local C = ffi.C

local byte = string.byte
local char = string.char
local floor = math.floor
local format = string.format

local fsrc, fdst
local fsrcp = 0

local function Exit()
	if fdst then fdst:close() end
	if fsrc then fsrc:close() end
	os.exit(0)
end

local function Assert(x, ...)
	if x then return x, ... end
	print("ERROR: " .. ...)
	Exit()
end

local function MB_WC(src, cp)
	local srclen = #src
	local dstlen = srclen * 2
	local dst = ffi.new("char[?]", dstlen)
	dstlen = C.MultiByteToWideChar(cp or 0, 0, src, srclen, dst, dstlen) * 2
	return ffi.string(dst, dstlen)
end

local function WC_MB(src, cp)
	local srclen = floor(#src / 2)
	local dstlen = srclen * 3
	local dst = ffi.new("char[?]", dstlen)
	dstlen = C.WideCharToMultiByte(cp or 0, 0, src, srclen, dst, dstlen, nil, nil)
	return ffi.string(dst, dstlen)
end

local function UTF8_JIS(s)
	return WC_MB(MB_WC(s, 65001), 932)
end

local function UTF8_GBK(s)
	return WC_MB(MB_WC(s, 65001), 936)
end

local function JIS_GBK(s)
	return WC_MB(MB_WC(s, 932), 936)
end

local function DumpBin(s)
	for i = 1, #s do
		io.stdout:write(format("%02X ", s:byte(i)))
		if i % 16 == 0 then print() end
	end
	print()
end

local function Main()
	if not arg[3] then
		print("usage: lua modtob.lua <input-filename.tob> <input-filename.txt> <output-filename.new>")
		Exit()
	end

	io.stdout:write(arg[1] .. " + " .. arg[2] .. " => " .. arg[3] .. " ... ")

	fsrc = Assert(io.open(arg[2], "r"))
	local src = Assert(fsrc:read("*a"))
	fsrc:close()
	fsrc = nil

	local txt, unu = {}, {}
	local n = 0
	for a, b, c, d in src:gmatch("○(%w+)○([^\n]*).-●(%w+)●([^\n]*)") do
		if a ~= c then
			print("ERROR: unmatched tag: " .. a .. " and " .. c)
			Exit()
		end
		local i = b:find("//", 1, true)
		if i then b = b:sub(1, i-1) end
		b = UTF8_JIS(b)
		d = UTF8_GBK(format("%q", d):sub(2,-2)):gsub("'","\\'")
		if not txt[b] then
			txt[b] = {}
			unu[b] = {}
		end
		txt[b][#txt[b]+1] = d
		unu[b][#unu[b]+1] = a
		n = n + 1
	end
	io.stdout:write("[" .. n .. "] ... ")

	n = 0
	fdst = Assert(io.open(arg[3], "wb"))
	for line in io.lines(arg[1]) do
		local i, j = 0
		while true do
			i, j = line:find(" '.-' ", i+1)
			if i then
				i = i + 2; j = j - 2
				local src = line:sub(i, j):gsub("''", ""):gsub("\\\"","\""):gsub("\\'","'")
				local dst = (txt[src] or {})[1]
				if dst then
					table.remove(txt[src], 1)
					table.remove(unu[src], 1)
					dst = line:sub(1, i-1) .. dst
					i = #dst + 1
					line = dst .. line:sub(j+1)
					n = n + 1
				elseif src:byte(1) == 0x22 and src:byte(-1) == 0x22 then
					src = src:sub(2, -2)
					dst = (txt[src] or {})[1]
					if dst then
						table.remove(txt[src], 1)
						table.remove(unu[src], 1)
						dst = line:sub(1, i-1) .. "\\\"" .. dst .. "\\\""
						i = #dst + 1
						line = dst .. line:sub(j+1)
						n = n + 1
					end
				end
			else
				break
			end
		end
		Assert(fdst:write(line, "\r\n"))
	end
	io.stdout:write("[" .. n .. "] ... ")

	print("OK!")

	local hasnun = false
	for _, v in pairs(unu) do
		for _, p in ipairs(v) do
			io.stdout:write("\t", p)
			hasnun = true
		end
	end
	if hasnun then
		io.stdout:write("\n")
	end

	Exit()
end

Main()
